﻿using DocumentFormat.OpenXml.Wordprocessing;
using FileManager.Model;
using FileManager.Util;
using FileManager.ViewModel;
using Stateless;
using Stateless.Graph;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using Windows.ApplicationModel.Calls;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;

namespace FileManager.MyProcess
{

    internal class BookImportProcess
    {
        // 定义状态
        public enum State
        {
            开始,//开始
            导入XML文件,
            导入新委托书文件夹,
            文件名检查,//检查文件名称
            重名文件处理,//确定文件是否相同
            文件覆盖,//覆盖文件
            旧文件迁移,//移动文件
            文件哈希值检查,//检查哈希
            文件地址更新,//更新文件地址
            新文件归位,//复制文件到指定地址
            元数据更改,//对改变保存
            结束//结束
        }

        // 定义触发器
        public enum Trigger
        {
            NeedXml,
            NeedBookDir,
            ImportReady,
            AllProcessingDone,
        }
    }

    /// <summary>
    /// 
    /// </summary>
    internal class BookSaveProcess
    {
        private BookWindowViewModel View { init; get; }
       
        private StateMachine<State, Trigger> SM;
        private StateMachine<State, Trigger>.TriggerWithParameters<FileInfo> updatAddressTrigger;


        private BitmapImage disPlayPic;
        private string _savePath;
        private string FileName => Path.GetFileNameWithoutExtension(_savePath);
        private string SavePath => _savePath;
        private string picPath { get; set; }

        private bool isReplaced = false;
        // 定义状态
        public enum State
        {
            开始,//开始
            文件名检查,//检查文件名称
            重名文件处理,//确定文件是否相同
            文件覆盖,//覆盖文件
            旧文件迁移,//移动文件
            文件哈希值检查,//检查哈希
            文件地址更新,//更新文件地址
            新文件归位,//复制文件到指定地址
            元数据更改,//对改变保存
            结束//结束
        }

        // 定义触发器
        public enum Trigger
        {
            Init,
            SameNameFileFound,//存在同名文件
            NoSameNameFile,//没有同名文件
            IsOriginalImage,// 是图片的原始文件
            DifferentFile,//是不同的文件
            NameDedupeDone,//同文件名去重结束
            NoHashMatchFound,//没有同哈希文件
            HashMatchFound,//有同哈希文件
            HashDedupeDone,//哈希去重结束
            AllProcessingDone,
        }
        private bool BeReplace=false;
        // 动作方法
        private void CheckForFileName()
        {
            if (File.Exists(this._savePath))
            {
               BeReplace=AskReplace();
               Fire(Trigger.SameNameFileFound);
            }
            else
            {
                Fire(Trigger.NoSameNameFile);
            }
        }
        private bool fileSame(string fileA,string fileB)
        {
            return fileA.ToUpper().StartsWith(fileB.ToUpper());
        }
        private bool AskReplace()
        {
            PicCompareWindow picCompare = new PicCompareWindow(SavePath, disPlayPic);
            bool? diaglogResult = picCompare.ShowDialog();
            return diaglogResult.HasValue && diaglogResult.Value;

        }
        private void IdentifyFile()
        {
            Debug.WriteLine("Determining if the file is the same as A...");
            //先剔除要保存的文件已存在Meta信息
            View.removeLetterMeta(SavePath);
            //如果是同一个文件，只需要完成图片自更新
            if (fileSame(SavePath,picPath))
            {
                Fire(Trigger.IsOriginalImage);
            }
            else
            {
                Fire(Trigger.DifferentFile);
            }
        }

        private void OverwriteContent()
        {
            Console.WriteLine("Overwriting file content...");
            disPlayPic.Update(SavePath);
            isReplaced = true;
            Fire(Trigger.NameDedupeDone);

        }

        private void MoveFileToNewLocation()
        {
            // 获得父目录路径
            string parentPath = Path.GetDirectoryName(SavePath)!;
            string delDir = Path.Combine(parentPath, "del");
            Directory.CreateDirectory(delDir);
            string desPath = Path.Combine(delDir, FileName + GlobalData.JPGD);
            // 构建新路径并移动文件
            while (File.Exists(desPath))
            {
                desPath = Path.Combine(delDir, FileName + "_" + DateTime.Now.ToString("yyMMddhhmmss") + GlobalData.JPGD);
                Task.Delay(1000).Wait();
            }
            File.Move(SavePath, desPath);
            Fire(Trigger.NameDedupeDone);
        }
        private FileInfo fi;
        private void CheckSameHash()
        {
            string hash = HashHelper.GetFileHash256(this.picPath);
            if(View.existsFile.TryGetValue(hash,out fi))
            {
                Fire(Trigger.HashMatchFound);
            }
            else
            {
                Fire(Trigger.NoHashMatchFound);
            }
           
        }
        private void CopyFile()
        {
            File.Copy(picPath, SavePath);
            Fire(Trigger.HashDedupeDone);
        }
        private void ChangeFileAddress()
        {

            if (fi.FullName != SavePath)
            {
                string nameNew = Path.GetFileNameWithoutExtension(SavePath);
                string nameOld = Path.GetFileNameWithoutExtension(fi.FullName);
                if (MessageBoxResult.Yes == System.Windows.MessageBox.Show($"该文件已存在，是否将名称从【{nameOld}】-->【{nameNew}】", "提示", MessageBoxButton.YesNo))
                {
                    File.Move(fi.FullName, SavePath);
                }
                else
                {
                    Fire(Trigger.AllProcessingDone);
                    return;
                }
            }
            Fire(Trigger.HashDedupeDone);
        }

        private void SaveChange()
        {
            View.saveData(SavePath);
            Fire(Trigger.AllProcessingDone);
        }

        public void Fire(Trigger trigger)
        {
            SM.Fire(trigger);
        }
        public void Init()
        {
            SM.Fire(Trigger.Init);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="viewModel">当前view页面</param>
        /// <param name="disPlayPic">需要保存的图片（可能是修改后）</param>
        /// <param name="savePath">保存地址</param>
        /// <param name="letterPath">当前委托书地址</param>
        internal BookSaveProcess(BookWindowViewModel viewModel,BitmapImage disPlayPic,string savePath,string letterPath)
        {

            this.disPlayPic = disPlayPic;
            this._savePath = savePath;
            this.View = viewModel;
            this.picPath=letterPath;
            SM = new StateMachine<State, Trigger>(State.开始);

            SM.Configure(State.开始)
               .Permit(Trigger.Init, State.文件名检查);


            //检测是否有同名文件
            SM.Configure(State.文件名检查)
                .OnEntry(CheckForFileName)
                .PermitIf(Trigger.SameNameFileFound, State.重名文件处理, () => BeReplace)
                .PermitIf(Trigger.SameNameFileFound, State.结束, () => !BeReplace)
                .Permit(Trigger.NoSameNameFile, State.文件哈希值检查);

            //检测是否为同样的文件
            SM.Configure(State.重名文件处理)
                .OnEntry(IdentifyFile)
                .Permit(Trigger.IsOriginalImage, State.文件覆盖)
                .Permit(Trigger.DifferentFile, State.旧文件迁移);


            //覆盖文件
            SM.Configure(State.文件覆盖)
                .OnEntry(OverwriteContent)
                .Permit(Trigger.NameDedupeDone, State.文件哈希值检查);

            //移动文件
            SM.Configure(State.旧文件迁移)
                .OnEntry(MoveFileToNewLocation)
                .Permit(Trigger.NameDedupeDone, State.文件哈希值检查);


            //检查是否存在同哈希的文件
            SM.Configure(State.文件哈希值检查)
                .OnEntry(CheckSameHash)
                .Permit(Trigger.NoHashMatchFound, State.新文件归位)
                .Permit(Trigger.HashMatchFound, State.文件地址更新);


            //没有同哈希，则复制过去
            SM.Configure(State.新文件归位)
                .OnEntry(CopyFile)
                .Permit(Trigger.HashDedupeDone, State.元数据更改);


            //有同哈希则保存
            SM.Configure(State.文件地址更新)
                .OnEntry(ChangeFileAddress)
                .Permit(Trigger.HashDedupeDone, State.元数据更改)
                .Permit(Trigger.AllProcessingDone, State.结束);

            SM.Configure(State.元数据更改)
                .OnEntry(SaveChange)
                .Permit(Trigger.AllProcessingDone,State.结束);

            string graph = MermaidGraph.Format(SM.GetInfo());

            Debug.WriteLine(graph);
        }
    } 
}







